package com.daguchuangyi.erp_android.productlist.classifiaction;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;

import com.daguchuangyi.erp_android.ErpApplication;
import com.daguchuangyi.erp_android.manager.NetworkManager;
import com.daguchuangyi.erp_android.manager.ParameterManager;
import com.daguchuangyi.erp_android.manager.networkservice.ProductService;
import com.daguchuangyi.erp_android.model.LocalMediaWrapper;
import com.daguchuangyi.erp_android.model.category.Category;
import com.daguchuangyi.erp_android.model.product.SimalarProductResult;
import com.daguchuangyi.erp_android.util.ImageUtil;
import com.google.gson.Gson;
import com.luck.picture.lib.entity.LocalMedia;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import rx.Observable;

/**
 * Created by lijianjian on 2018/3/17.
 */

public class ClassificationManager {
    private static final String TAG = "ClassificationManager";

    public static final String ID_ALL_PRODUCT = "ID_ALL_PRODUCT";
    public static final String ID_NO_IMAGE_TAG = "ID_NO_IMAGE_TAG";
    public static final String ID_NO_CATEGORY_TAG = "0";

    public static final String MODE_EXTRA_KEY_WORD = "查询结果";
    public static final String MODE_EXTRA_KEY_LIKE = "查找相似";
    public static final String MODE_EXTRA_KEY_RECOGNITION = "图像识别结果";
    public static final String MODE_EXTRA_PARAMS_FILTER = "参数查询结果";

    private List<ClassificationModel> mClassificationModels = new ArrayList<>();

    private Map<Integer, ClassificationModel> mClassificationModelMap = new HashMap<>();
    //    private String mExtralMode = "";
    private String mKeyword = "";
    private String mSimlarProductId = "";
    private String mSimalarClassificationId = "";
    private LocalMediaWrapper mLocalMedia = null;
    private boolean mIsTotalRecognize = false;
    //    private SimalarProductResult mRecognizeProductResult = null;
//    private SimalarProductResult mLikelyProductResult = null;
    private SimalarProductResult mLeatestSimalarProductResult = null;
    private List<String> mExtralModes = new ArrayList<>();

    public String getExtralMode() {
        if (mExtralModes.size() == 0) {
            return "";
        } else {
            return mExtralModes.get(mExtralModes.size() - 1);
        }
    }

    public boolean hasImageRecognizeChecke() {
        return mExtralModes.contains(MODE_EXTRA_KEY_RECOGNITION);
    }

    public boolean hasParamFilterChecked() {
        return mExtralModes.contains(MODE_EXTRA_PARAMS_FILTER);
    }

    public String getSimalarClassificationId() {
        return mSimalarClassificationId;
    }

    private LocalMediaWrapper getLocalMedia() {
        return mLocalMedia;
    }

    private boolean isTotalRecognize() {
        return mIsTotalRecognize;
    }

    public SimalarProductResult getLeatestSimalarProductResult() {
        return mLeatestSimalarProductResult;
    }

    public Observable<SimalarProductResult> loadLikelyProductList(boolean forceRefresh) {
        if (!forceRefresh && mLeatestSimalarProductResult != null) {
            return Observable.just(mLeatestSimalarProductResult);
        } else {
            String productImageId = ClassificationManager.getInstance().getSimlarProductId();
            Map<String, Object> queryMap = new HashMap<>();
            queryMap.put("imageId", productImageId);
            String classificationId = ClassificationManager.getInstance().getSimalarClassificationId();
            if (classificationId.equals("-1")) {
                classificationId = "0";
            }
            queryMap.put("categoryId", classificationId);
//            Map<String, Object> bodyMap = new HashMap<>();
//            if (mLeatestSimalarProductResult != null) {
//                bodyMap.put("ids", mLeatestSimalarProductResult.getIds());
//            }
            return NetworkManager.getInstance().getRetrofit().create(ProductService.class)
                    .findSimalarProductList(queryMap)
                    .doOnNext(simalarProductResult -> mLeatestSimalarProductResult = simalarProductResult);
        }
    }

    public Observable<SimalarProductResult> loadRecognizeProductList(boolean forceRefresh) {
        if (!forceRefresh && mLeatestSimalarProductResult != null) {
            return Observable.just(mLeatestSimalarProductResult);
        } else {
            LocalMediaWrapper localMediaWrapper = ClassificationManager.getInstance().getLocalMedia();
            LocalMedia localMedia = localMediaWrapper.getLocalMedia();
            boolean isTotalRecognize = ClassificationManager.getInstance().isTotalRecognize();
//            File cropFile = new File(localMedia.getCutPath());
            String filePath = localMedia.getPath();
            Bitmap original = BitmapFactory.decodeFile(filePath);
            String compressFilePath = ErpApplication.getAppContext().getCacheDir() + File.separator + "upload_temp.jpg";
//            String compressFilePath = Environment.getExternalStorageDirectory() + File.separator + "upload_temp.jpg";
//            ByteArrayOutputStream out = new ByteArrayOutputStream();
            File compressFile = new File(compressFilePath);
            FileOutputStream fileOutputStream = null;
            try {
                fileOutputStream = new FileOutputStream(compressFile);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            original.compress(Bitmap.CompressFormat.JPEG, 80, fileOutputStream);

            try {
                ImageUtil.saveExif(filePath, compressFilePath);
            } catch (Exception e) {
                e.printStackTrace();
                Log.e(TAG, "copy exif error" + e.getMessage());
            }

//            byte[] data = out.toByteArray();
//            File file = new File(compressFilePath);

            RequestBody requestFile = RequestBody.create(MediaType.parse("image/jpg"), compressFile);
            MultipartBody.Part fileBody = MultipartBody.Part.createFormData("file", compressFile.getName(), requestFile);

            Map<String, Object> queryMap = new HashMap<>();
            String categoryId = ClassificationManager.getInstance().getClassificationId();
            switch (categoryId) {
                case ClassificationManager.ID_NO_IMAGE_TAG:
                    break;
                case ClassificationManager.ID_ALL_PRODUCT:
                    break;
                default:
                    queryMap.put("categoryId", categoryId);
//                params.put("categoryId", categoryId);
            }
            queryMap.put("findMode", isTotalRecognize ? "1" : "2");
//        queryMap.put("page", page);
//        queryMap.put("limit", 32);

//            BitmapFactory.Options op = new BitmapFactory.Options();
//            op.inJustDecodeBounds = true;
//            BitmapFactory.decodeFile(filePath, op);
//            JUtils.Log("width is : " + op.outWidth + ", height is : " + op.outHeight);

            Map<String, Object> bodyMap = new HashMap<>();
            bodyMap.put("x", localMediaWrapper.getX());
            bodyMap.put("y", localMediaWrapper.getY());
            bodyMap.put("width", localMediaWrapper.getWidth());
            bodyMap.put("height", localMediaWrapper.getHeight());
            Log.e(TAG, String.format("x: %d,y: %d,width: %d,height: %d", localMediaWrapper.getX(),
                    localMediaWrapper.getY(), localMediaWrapper.getWidth(), localMediaWrapper.getHeight()));

//        String descriptionString = "hello, 这是文件描述";
            RequestBody description = RequestBody.create(MediaType.parse("multipart/form-data"), new Gson().toJson(bodyMap));
            return NetworkManager.getInstance().getRetrofit().create(ProductService.class)
                    .recognizeImage(fileBody, description, queryMap)
                    .doOnNext(simalarProductResult -> mLeatestSimalarProductResult = simalarProductResult);

        }
    }


    private static final ClassificationManager ourInstance = new ClassificationManager();

    private OnClassificationChangeListener mClassificationChangeListener;

    public static ClassificationManager getInstance() {
        return ourInstance;
    }

    private ClassificationManager() {
    }

    public void setClassificationChangeListener(OnClassificationChangeListener classificationChangeListener) {
        mClassificationChangeListener = classificationChangeListener;
    }

    public String getKeyword() {
        return mKeyword;
    }

    public String getSimlarProductId() {
        return mSimlarProductId;
    }

    public Observable<List<ClassificationModel>> loadClassificationInfo(boolean forceRefresh) {
        if (!forceRefresh && mClassificationModels != null && mClassificationModels.size() != 0) {
            return Observable.just(mClassificationModels);
        }
        return NetworkManager.getInstance().getRetrofit().create(ProductService.class)
                .getCategory()
                .flatMap(categoryWrapper -> {
                    List<ClassificationModel> classificationModels = new ArrayList<>();

                    {
                        int withoutCategoryCount = categoryWrapper.getWithoutCategoryCount();
                        ClassificationModel withoutCategory = new ClassificationModel();
                        withoutCategory.setTitle("未分类商品");
                        withoutCategory.setCount(withoutCategoryCount);
                        withoutCategory.setLevel(0);
                        withoutCategory.setId(ID_NO_CATEGORY_TAG);
                        classificationModels.add(withoutCategory);
                    }

                    List<Category> categories = categoryWrapper.getCategories();
                    for (Category item : categories) {
                        ClassificationModel classificationModel = convertToClassification(item, 0);
                        classificationModels.add(classificationModel);
                    }

                    int withoutImageCount = categoryWrapper.getWithoutImageIdCount();
                    {
                        ClassificationModel withoutImage = new ClassificationModel();
                        withoutImage.setTitle("无识别图片的商品");
                        withoutImage.setCount(withoutImageCount);
                        withoutImage.setId(ID_NO_IMAGE_TAG);
                        withoutImage.setLevel(0);
                        classificationModels.add(withoutImage);
                    }

                    return Observable.just(classificationModels);
                })
                .doOnNext(classificationModels -> {
                    mClassificationModels.clear();
                    mClassificationModels.addAll(classificationModels);
                });
    }

    private ClassificationModel convertToClassification(Category category, int level) {
        ClassificationModel result = new ClassificationModel();
        result.setId(String.valueOf(category.getId()));
        result.setCount(category.getProductCount());
        result.setLevel(level);
        result.setTitle(category.getName());
        int tempLevel = level;
        if (category.getSubCategories() != null && category.getSubCategories().size() != 0) {
            tempLevel++;
            int countAmount = 0;
            for (Category subItem : category.getSubCategories()) {
                ClassificationModel subClass = convertToClassification(subItem, tempLevel);
                countAmount += subClass.getCount();
                result.addSubItem(subClass);
            }
            if (tempLevel == 1) {
                result.setCount(countAmount);
            }
        }
        return result;
    }

    public void refreshClassification(Map<Integer, ClassificationModel> modelMap) {
        Log.w(TAG, "clear was called. refreshClassification");
        mClassificationModelMap.clear();
        mClassificationModelMap.putAll(modelMap);
        mExtralModes.clear();
//        mExtralModes = new ArrayList<>();
        mKeyword = "";
//        mLikelyProductResult = null;
//        mRecognizeProductResult = null;
        mLeatestSimalarProductResult = null;
        ParameterManager.getInstance().clearParamsCheckStatus();
        if (mClassificationChangeListener != null) {
            mClassificationChangeListener.onClassificationChanged(getCurrentClassification());
        }
    }

//    public void setExtralMode(String extralMode) {
//        mExtralMode = extralMode;
//        if (mClassificationChangeListener != null) {
//            mClassificationChangeListener.onClassificationChanged(getCurrentClassification());
//        }
//    }

    public boolean hasClassificationCheck() {
        return mClassificationModelMap.size() != 0;
    }

    public Map<Integer, ClassificationModel> getClassificationTree(String classificationId) {
        Map<Integer, ClassificationModel> resultMap = new HashMap<>();
        for (ClassificationModel item : mClassificationModels) {
            Map<Integer, ClassificationModel> subMap = depthOrderTraversal(item, classificationId);
            if (subMap.size() != 0) {
                resultMap.clear();
                resultMap.putAll(subMap);
                break;
            }
        }

        return resultMap;
    }

    public String getClassificationName(String classificationId) {
        Map<Integer, ClassificationModel> resultMap = getClassificationTree(classificationId);
//        Map<Integer, String> resultMap = new HashMap<>();
//        for (ClassificationModel item : mClassificationModels) {
//            Map<Integer, ClassificationModel> subMap = depthOrderTraversal(item, classificationId);
//            if (subMap != null && subMap.size() != 0) {
//                resultMap.clear();
//                resultMap.putAll(subMap);
//                break;
//            }
//        }
        if (resultMap.size() == 0) {
            return "未分类商品";
        } else {
            int size = resultMap.size();
            String result = "";
            for (int i = 0; i < size; i++) {
                if (i != 0) {
                    result += ("\\" + resultMap.get(i).getTitle());
                } else {
                    result += resultMap.get(i).getTitle();
                }
            }
            return result;
        }
    }

    @NonNull
    public Map<Integer, ClassificationModel> depthOrderTraversal(ClassificationModel root, String id) {
        Map<Integer, ClassificationModel> resultMap = new HashMap<>();
        if (root == null) {
            return resultMap;
        }
        ArrayDeque<ClassificationModel> stack = new ArrayDeque<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            ClassificationModel node = stack.pop();
            int level = node.getLevel();
            resultMap.put(level, node);
            int mapSize = resultMap.size();
            for (int i = level + 1; i < mapSize; i++) {
                resultMap.remove(i);
            }
            if (TextUtils.equals(node.getId(), id)) {
                return resultMap;
            }
            if (node.hasSubItem()) {
                for (int i = 0; i < node.getSubItems().size(); i++) {
                    stack.push(node.getSubItem(i));
                }
            }
        }
        return new HashMap<>();
    }


    public String getCurrentClassification() {
        String result = "";
//        if (TextUtils.equals(mExtralMode, MODE_EXTRA_KEY_LIKE)) {
//            result = ClassificationManager.getInstance().getClassificationName(mSimalarClassificationId);
//        } else {
        int size = mClassificationModelMap.size();
        if (size == 0) {
            result += "所有商品";
        } else {
            for (int i = 0; i < size; i++) {
                result += mClassificationModelMap.get(i).getTitle();
                if (i != size - 1) {
                    result += "\\";
                }
            }
        }
//        }
        for (String mode : mExtralModes) {
            result += "\\" + mode;
        }
//        if (!TextUtils.isEmpty(mExtralMode)) {
//            result += "\\" + mExtralMode;
//        }
        return result;
    }

    public void clear() {
        Log.w(TAG, "clear was called. clear");
        mExtralModes.clear();
        mClassificationModelMap.clear();
        mLeatestSimalarProductResult = null;
//        mLikelyProductResult = null;
//        mRecognizeProductResult = null;
//        if (mClassificationChangeListener != null) {
//            mClassificationChangeListener.onClassificationChanged(getCurrentClassification());
//        }
    }

    public String getClassificationId() {
        int size = mClassificationModelMap.size();
        if (size > 0) {
            return mClassificationModelMap.get(size - 1).getId();
        } else {
            return ClassificationManager.ID_ALL_PRODUCT;
        }
    }

    public void quitRecognitionMode() {
//        mExtralMode = "";
        mExtralModes.clear();
        mLeatestSimalarProductResult = null;
        ParameterManager.getInstance().clearParamsCheckStatus();
//        mClassificationModelMap.clear();
        if (mClassificationChangeListener != null) {
            mClassificationChangeListener.onClassificationChanged(getCurrentClassification());
        }
    }

    public void changeToRecognitionMode(LocalMediaWrapper localMediaWrapper, boolean isTotalRecognize) {
//        mExtralMode = MODE_EXTRA_KEY_RECOGNITION;
        appendMode(MODE_EXTRA_KEY_RECOGNITION);
        mLocalMedia = localMediaWrapper;
        mIsTotalRecognize = isTotalRecognize;
//        mLeatestSimalarProductResult = null;
//        mLikelyProductResult = null;
//        mRecognizeProductResult = null;
        if (mClassificationChangeListener != null) {
            mClassificationChangeListener.onClassificationChanged(getCurrentClassification());
        }
    }

    public void changeToSearchResultMode(String keyword) {
//        mExtralMode = MODE_EXTRA_KEY_WORD;
        Log.w(TAG, "clear was called. changeToSearchResultMode");
        mExtralModes.clear();
        mExtralModes.add(MODE_EXTRA_KEY_WORD);
        mKeyword = keyword;
        mClassificationModelMap.clear();
        mLeatestSimalarProductResult = null;
//        mLikelyProductResult = null;
//        mRecognizeProductResult = null;
        if (mClassificationChangeListener != null) {
            mClassificationChangeListener.onClassificationChanged(getCurrentClassification());
        }
    }

    public void changeToSimilarMode(String id, String paramId) {
//        mExtralMode = MODE_EXTRA_KEY_LIKE;
        Log.w(TAG, "clear was called. changeToSimilarMode");
        appendMode(MODE_EXTRA_KEY_LIKE);
        mSimlarProductId = id;
        mSimalarClassificationId = paramId;
//        mLeatestSimalarProductResult = null;
//        mLikelyProductResult = null;
//        mRecognizeProductResult = null;
        mClassificationModelMap.clear();
        mClassificationModelMap.putAll(getClassificationTree(paramId));
        if (mClassificationChangeListener != null) {
            mClassificationChangeListener.onClassificationChanged(getCurrentClassification());
        }
    }

    public void changeToParamsFilterMode() {
//        mExtralMode = MODE_EXTRA_PARAMS_FILTER;
        appendMode(MODE_EXTRA_PARAMS_FILTER);
//        mLeatestSimalarProductResult = null;
//        mLikelyProductResult = null;
//        mRecognizeProductResult = null;
        if (mClassificationModelMap != null) {
            mClassificationChangeListener.onClassificationChanged(getCurrentClassification());
        }
    }

    public void appendMode(String mode) {
        if (mExtralModes.contains(mode)) {
            mExtralModes.remove(mode);
        }
        mExtralModes.add(mode);
    }

    public interface OnClassificationChangeListener {
        void onClassificationChanged(String classification);
    }
}
